/******************************************************************************
    File    :   ChessGame.cs
    Version :   1.0.0.0
 	Date    :	18/10/2008   2:55
-------------------------------------------------------------------------------
*	Name    :	Nguyen Hung Cuong
*   Class   :   TH2005
*   StuID   :   0512085
*   Mail    :   nhc.hcmuns@gmail.com
-------------------------------------------------------------------------------
	Purpose :	
******************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace _512085_CaroChess
{
    /// <summary>
    /// Chess game
    /// </summary>
    public class ChessGame
    {
        private int _turn;
        private bool _isFinished;
        private ChessPlayer _player1;
        private ChessPlayer _player2;
        private XPoint _lastMove;
        private ChessBoard _board;

        public ChessBoard Board
        {
            get { return _board; }
        }

        public int Turn
        {
            get { return _turn; }
        }

        public XPoint LastMove
        {
            get { return _lastMove; }
        }

        /// <summary>
        /// Init the game
        /// </summary>
        /// <param name="numRows"></param>
        /// <param name="numCols"></param>
        public ChessGame(byte numRows, byte numCols)
        {
            _turn = 1;       // player 1 go first
            _board = new ChessBoard(numRows, numCols);
            _player1 = new HumanPlayer(1);
            _player2 = new HumanPlayer(2);
            _lastMove = new XPoint();
            _isFinished = false;
        }

        /// <summary>
        /// Add chessman to player chessmen and switch player
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void MoveChess(byte x, byte y)
        {
            _lastMove.Update(x, y);

            if (_turn == 1)
            {
                _board[x,y] = _player1.Id;
                _player1.Move(this);
                _turn = 2;
            }

            else if(_turn == 2)
            {
                _board[x,y] = _player2.Id;
                _player2.Move(this);
                _turn = 1;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public byte GetPlayerIdAt(byte x, byte y)
        {
            if (_board[x,y] == _player1.Id)
                return 1;
            else if (_board[x,y] == _player2.Id)
                return 2;
            return 0;
        }

        /// <summary>
        /// Reset game
        /// </summary>
        public void Reset()
        {
            _turn = 1;
            _isFinished = false;
            _player1 = new HumanPlayer(1);
            _player2 = new HumanPlayer(2);
            _board.Reset();
        }

        /// <summary>
        /// Save the game
        /// </summary>
        /// <param name="filename"></param>
        public void SaveGame(string filename)
        {
            XmlDocument document = new XmlDocument();
            
            XmlElement caroEle = document.CreateElement("Caro");
            caroEle.SetAttribute("Turn", _turn.ToString());

            for (byte i = 0; i < _board.Rows; ++i )
            {
                for (byte j = 0; j < _board.Cols; ++j )
                {
                    if(_board[i,j] != 0)
                    {
                        XmlElement chessmanEle = document.CreateElement("ChessMan");
                        chessmanEle.SetAttribute("x", i.ToString());
                        chessmanEle.SetAttribute("y", j.ToString());
                        chessmanEle.SetAttribute("Player", GetPlayerIdAt(i, j).ToString());

                        caroEle.AppendChild(chessmanEle);
                    }
                }
            }

            document.AppendChild(caroEle);
            XXml.Save(document, filename);
        }

        /// <summary>
        /// Load the game
        /// </summary>
        /// <param name="filename"></param>
        public void LoadGame(string filename)
        {
            XmlElement caroEle = XXml.Load(filename);

            foreach (XmlElement chessman in caroEle.ChildNodes)
            {
                byte x = Convert.ToByte(chessman.GetAttribute("x"));
                byte y = Convert.ToByte(chessman.GetAttribute("y"));
                _board[x, y] = Convert.ToByte(chessman.GetAttribute("Player"));
            }
        }

        /// <summary>
        /// Game is ready?
        /// </summary>
        /// <returns></returns>
        public bool IsReady()
        {
            return !_isFinished;
        }

        /// <summary>
        /// Who is the winner ?
        /// </summary>
        /// <returns> 
        /// 0 : no one win
        /// 1 : player1 win
        /// 2 : player2 win
        /// </returns>
        public int CheckForWinner()
        {
            ChessPlayer currentPlayer;
            if (_turn == 2)
                currentPlayer = _player1;
            else
                currentPlayer = _player2;

            byte i,j;
            byte count;

            // up and down
            count = 1;
            i = _lastMove.X;
            j = _lastMove.Y;
            while (i > 0)
            {
                i--;

                if (_board[i, j] == currentPlayer.Id)
                    count++;
                else break;
            }

            i = _lastMove.X;
            j = _lastMove.Y;
            while (i < _board.Rows-1)
            {
                i++;

                if (_board[i, j] == currentPlayer.Id)
                    count++;
                else break;
            }
            if (count >= 5)
            {
                _isFinished = true;
                return _turn;
            }


            // left and right
            count = 1;
            i = _lastMove.X;
            j = _lastMove.Y;
            while (j > 0)
            {
                j--;

                if (_board[i, j] == currentPlayer.Id)
                    count++;
                else break;
            }

            i = _lastMove.X;
            j = _lastMove.Y;
            while (j < _board.Cols-1)
            {
                j++;

                if (_board[i, j] == currentPlayer.Id)
                    count++;
                else break;
            }
            if (count >= 5)
            {
                _isFinished = true;
                return _turn;
            }


            // down-right and up-left
            count = 1;
            i = _lastMove.X;
            j = _lastMove.Y;
            while (i > 0 && j > 0)
            {
                i--; j--;

                if (_board[i, j] == currentPlayer.Id)
                    count++;
                else break;
            }

            i = _lastMove.X;
            j = _lastMove.Y;
            while (i < _board.Cols-1 && j < _board.Cols-1)
            {
                i++; j++;

                if (_board[i, j] == currentPlayer.Id)
                    count++;
                else break;
            }
            if (count >= 5)
            {
                _isFinished = true;
                return _turn;
            }


            // down-left and up-right
            count = 1;
            i = _lastMove.X;
            j = _lastMove.Y;
            while (i < _board.Cols-1 && j > 0)
            {
                i++; j--;

                if (_board[i, j] == currentPlayer.Id)
                    count++;
                else break;
            }

            i = _lastMove.X;
            j = _lastMove.Y;
            while (i > 0 && j < _board.Cols-1)
            {
                i--; j++;

                if (_board[i, j] == currentPlayer.Id)
                    count++;
                else break;
            }
            if (count >= 5)
            {
                _isFinished = true;
                return _turn;
            }

            return 0;
        }
    }
}
